package agend.client.gui.panels.agend;


import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

import org.freixas.jcalendar.DateEvent;
import org.freixas.jcalendar.DateListener;
import org.freixas.jcalendar.JCalendar;

import GoogleServices.GoogleCalendarCalls;
import agend.client.gui.utils.Broker;
import agend.client.gui.utils.HandlerView;
import agend.client.gui.utils.Observer;

import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.extensions.When;


///**
// *
// * @author Paolo
// */

/**
 * This code was edited or generated using CloudGarden's Jigloo
 * SWT/Swing GUI Builder, which is free for non-commercial
 * use. If Jigloo is being used commercially (ie, by a corporation,
 * company or business for any purpose whatever) then you
 * should purchase a license for each developer using Jigloo.
 * Please visit www.cloudgarden.com for details.
 * Use of Jigloo implies acceptance of these licensing terms.
 * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
 * THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
 * LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
 */
public class AgendPanel extends javax.swing.JPanel implements Observer{
	private JCalendar jCalendar;
	private JTable agendTable;
	private HashMap<Integer, List<MyEvent>> eventsMap;
	private int max;

	private void initGUI() {
		try {
			{


				HandlerView.getBroker().addObserver(this);


				this.setPreferredSize(new java.awt.Dimension(683, 412));
				GridBagLayout thisLayout = new GridBagLayout();
				this.setSize(683, 412);
				thisLayout.rowWeights = new double[] {0.1, 0.1, 0.1, 0.1};
				thisLayout.rowHeights = new int[] {7, 7, 7, 7};
				thisLayout.columnWeights = new double[] {0.1, 0.1, 0.1, 0.1};
				thisLayout.columnWidths = new int[] {7, 7, 7, 7};
				this.setLayout(thisLayout);
				this.setMinimumSize(new java.awt.Dimension(400, 300));
				this.setBackground(new java.awt.Color(255,255,255));

				agendTable = new JTable();

				agendTable.addMouseListener(new MouseAdapter() {
					@Override
					public void mouseClicked(MouseEvent e) {
						// TODO Auto-generated method stub
						super.mouseClicked(e);

						MyEvent event = null;
						ModelTableCalendar model = (ModelTableCalendar) agendTable.getModel();

						int rowSelected  = agendTable.getSelectedRow();
						int columnSelected = agendTable.getSelectedColumn();


						if(model.getValueAt(rowSelected, columnSelected) instanceof MyEvent)
						{	
							event = new MyEvent();
							event =(MyEvent) model.getValueAt(rowSelected, columnSelected);
						}

						DialogCalendarEventPanel dialogCalendarEventPanel = new DialogCalendarEventPanel(new Frame(),event);
						if(event != null){

							dialogCalendarEventPanel.setVisible(true);
						}

					}	
				});

				agendTable.setRowSelectionAllowed(true);

				agendTable.setModel(new ModelTableCalendar());
				agendTable.setDefaultRenderer(Object.class, new MyCellTableRenderer());


				agendTable.setRowHeight(42);

				this.addComponentListener(new ComponentListener() {

					@Override
					public void componentShown(ComponentEvent arg0) {
						// TODO Auto-generated method stub
						GregorianCalendar gregorianTodayDate = new GregorianCalendar();
						gregorianTodayDate.setTimeInMillis(System.currentTimeMillis());
						getWeekEventsOfSelectedDay(gregorianTodayDate);
						agendTable.updateUI();

					}

					@Override
					public void componentResized(ComponentEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void componentMoved(ComponentEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void componentHidden(ComponentEvent arg0) {
						// TODO Auto-generated method stub

					}
				});

				jCalendar = new JCalendar();
				jCalendar.addDateListener(new DateListener() {

					@Override
					public void dateChanged(DateEvent arg0) {
						Date dateClicked = jCalendar.getDate();
						GregorianCalendar gregorianDateClicked = new GregorianCalendar();
						gregorianDateClicked.setTimeInMillis(dateClicked.getTime());
						getWeekEventsOfSelectedDay(gregorianDateClicked);
						agendTable.updateUI();
					}
				});

				JScrollPane scrollPane = new JScrollPane(agendTable);
				this.add(jCalendar, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(50, 0, 0, 0), 0, 0));

				this.add(scrollPane, new GridBagConstraints(1, 1, 3, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
				scrollPane.setBackground(new java.awt.Color(255,255,255));

				updateUI();

			}
			{
				JLabel calendarlabel = new JLabel();
				this.add(calendarlabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
				calendarlabel.setIcon(new ImageIcon(getClass().getClassLoader().getResource("defaultImages/GoogleCalendarIcon.jpg")));
			}
		} catch(Exception e) {
			e.printStackTrace();
		}


	}
	public AgendPanel() {
		eventsMap = new HashMap<Integer, List<MyEvent>>();
		eventsMap.put(1, new ArrayList<MyEvent>());
		eventsMap.put(2, new ArrayList<MyEvent>());
		eventsMap.put(3, new ArrayList<MyEvent>());
		eventsMap.put(4, new ArrayList<MyEvent>());
		eventsMap.put(5, new ArrayList<MyEvent>());
		eventsMap.put(6, new ArrayList<MyEvent>());
		eventsMap.put(7, new ArrayList<MyEvent>());
		eventsMap.put(8, new ArrayList<MyEvent>());

		initGUI();

		agendTable.setBackground(Color.WHITE);
	}

	public JCalendar getJCalendar() {
		return jCalendar;
	}

	private class MyCellTableRenderer implements TableCellRenderer{

		@Override
		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) 
		{

			EventPanel panel = new EventPanel();
			panel.setBackground(Color.WHITE);
			if(value instanceof MyEvent)
			{

				MyEvent myEvent = (MyEvent) value;

				if(isSelected)
				{
					panel.setForeground(agendTable.getSelectionForeground());
					panel.setBackground(agendTable.getSelectionBackground());
				}
				else 
				{
					panel.setForeground(agendTable.getForeground());
					panel.setBackground(agendTable.getBackground());
				}			

				panel.setBackground(Color.ORANGE);

				GregorianCalendar from = new GregorianCalendar();
				from.setTimeInMillis(myEvent.getWhen().getStartTime().getValue());

				GregorianCalendar to = new GregorianCalendar();
				to.setTimeInMillis(myEvent.getWhen().getEndTime().getValue());

				int hourStart = from.get(Calendar.HOUR_OF_DAY);
				int minStart = from.get(Calendar.MINUTE);
				int hourEnd = to.get(Calendar.HOUR_OF_DAY);
				int minEnd = to.get(Calendar.MINUTE);

				String fromTo="";
				if(minStart==0)
					fromTo = hourStart+":"+minStart+"0 - "+hourEnd+":"+minEnd;
				if(minEnd==0)
					fromTo = hourStart+":"+minStart+" - "+hourEnd+":"+minEnd+"0";
				if(minStart==0 && minEnd==0)
					fromTo = hourStart+":"+minStart+"0 - "+hourEnd+":"+minEnd+"0";
				if(minStart!=0 && minEnd!=0) 
					fromTo = hourStart+":"+minStart+" - "+hourEnd+":"+minEnd;


				if(!myEvent.getCalendarEntry().getTitle().getPlainText().equals(""))
					panel.update(myEvent.getCalendarEntry().getTitle().getPlainText(), fromTo);
				else
					panel.update("Senza Titolo", fromTo);
			}

			return panel;
		}
	}


	/**
	 * Classe che gestisce il modello della tabella che contiene gli eventi  
	 * @author Paolo
	 *
	 */
	private class ModelTableCalendar extends AbstractTableModel {

		private static final long serialVersionUID = 1L;

		private String[] columnTitle = {"Monday","Tuesday", "Wednesday","Thursday","Friday","Saturday","Sunday"};

		@Override
		public String getColumnName(int index) {
			// TODO Auto-generated method stub
			return columnTitle[index];
		}

		@Override
		public int getColumnCount() {
			// TODO Auto-generated method stub
			return 7;
		}

		@Override
		public int getRowCount() {
			// TODO Auto-generated method stub
			return max;

		}

		@Override
		public Object getValueAt(int row, int col) {
			// TODO Auto-generated method stub

			if(col==0)
			{
				List<MyEvent> list = eventsMap.get(1);

				if(row < list.size())
					return list.get(row);
			}
			else if ( col == 1)
			{
				List<MyEvent> list = eventsMap.get(2);

				if(row < list.size())
					return list.get(row);

			}
			else if ( col == 2)
			{
				List<MyEvent> list = eventsMap.get(3);

				if(row < list.size())
					return list.get(row);
			}
			else if ( col == 3)
			{
				List<MyEvent> list = eventsMap.get(4);

				if(row < list.size())
					return list.get(row);
			}
			else if ( col == 4)
			{
				List<MyEvent> list = eventsMap.get(5);

				if(row < list.size())
					return list.get(row);
			}
			else if ( col == 5)
			{
				List<MyEvent> list = eventsMap.get(6);

				if(row < list.size())
					return list.get(row);
			}
			else if ( col == 6)
			{
				List<MyEvent> list = eventsMap.get(7);

				if(row < list.size())
					return list.get(row);
			}

			return "";
		}
	}

	private HashMap<Integer, List<MyEvent>> getWeekEventsOfSelectedDay(GregorianCalendar dateClicked)
	{
		//HashMap<Integer, List<MyEvent>> map = new HashMap<Integer, List<MyEvent>>();

		GoogleCalendarCalls g = Broker.getCalendarService();


		int dayOfWeek = dateClicked.get(Calendar.DAY_OF_WEEK);

		GregorianCalendar startWeekDay = new GregorianCalendar();
		startWeekDay.setTimeInMillis(dateClicked.getTimeInMillis());

		GregorianCalendar endWeekDay = new GregorianCalendar();
		endWeekDay.setTimeInMillis(dateClicked.getTimeInMillis());
		switch(dayOfWeek)
		{
		//domenica
		case 1 : {

			startWeekDay.add(Calendar.DAY_OF_MONTH, -6);

			break;
		}
		//lunedi
		case 2 : {
			endWeekDay.add(Calendar.DAY_OF_MONTH, +6);
			break;
		}
		//martedi
		case 3 : {
			startWeekDay.add(Calendar.DAY_OF_MONTH, -1);
			endWeekDay.add(Calendar.DAY_OF_MONTH, +5);
			break;
		}
		//mercoledi
		case 4 : {
			startWeekDay.add(Calendar.DAY_OF_MONTH, -2);
			endWeekDay.add(Calendar.DAY_OF_MONTH, +4);
			break;
		}
		//giovedi
		case 5 : {
			startWeekDay.add(Calendar.DAY_OF_MONTH, -3);
			endWeekDay.add(Calendar.DAY_OF_MONTH, +3);
			break;
		}
		//venerdi
		case 6 : {
			startWeekDay.add(Calendar.DAY_OF_MONTH, -4);
			endWeekDay.add(Calendar.DAY_OF_MONTH, +2);
			break;
		}
		//sabato
		case 7 : {
			startWeekDay.add(Calendar.DAY_OF_MONTH, -5);
			endWeekDay.add(Calendar.DAY_OF_MONTH, +1);
			break;
		}

		}

		startWeekDay.set(Calendar.HOUR_OF_DAY, 00);
		startWeekDay.set(Calendar.MINUTE, 01);

		endWeekDay.set(Calendar.HOUR_OF_DAY, 23);
		endWeekDay.set(Calendar.MINUTE, 59);

		int eventsByRangeSize = g.getEventsByRangeCalendarEventEntry(startWeekDay.getTimeInMillis(), endWeekDay.getTimeInMillis()).size();
		if(eventsByRangeSize == 0)
		{
			List<MyEvent> mondaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> tuesdaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> wednesdayList = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> thursdaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> fridaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> saturdaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> sundaylist = new ArrayList<AgendPanel.MyEvent>();
			
			eventsMap.put(1, mondaylist);
			eventsMap.put(2, tuesdaylist);
			eventsMap.put(3, wednesdayList);
			eventsMap.put(4, thursdaylist);
			eventsMap.put(5, fridaylist);
			eventsMap.put(6, saturdaylist);
			eventsMap.put(7, sundaylist);

			max=0;updateRow();
		}
		if(g!= null &&  eventsByRangeSize > 0)
		{
			List<CalendarEventEntry> events = g.getEventsByRangeCalendarEventEntry(startWeekDay.getTimeInMillis(), endWeekDay.getTimeInMillis());
			
			List<MyEvent> mondaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> tuesdaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> wednesdayList = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> thursdaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> fridaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> saturdaylist = new ArrayList<AgendPanel.MyEvent>();
			List<MyEvent> sundaylist = new ArrayList<AgendPanel.MyEvent>();

			for(int i=0; i < events.size(); i++ )

			{
				CalendarEventEntry event = events.get(i);

				List<When> whenList = event.getTimes();

				for(When when : whenList)
				{
					GregorianCalendar date = new GregorianCalendar();
					date.setTimeInMillis(when.getStartTime().getValue());

					int day = date.get(Calendar.DAY_OF_WEEK);


					MyEvent myEvent;
					switch(day)
					{
					case 1 : {
						myEvent = new MyEvent(event, when);
						sundaylist.add(myEvent);
						break;
					}
					case 2 : {
						myEvent = new MyEvent(event, when);
						mondaylist.add(myEvent);
						break;
					}
					case 3 : {
						myEvent = new MyEvent(event, when);
						tuesdaylist.add(myEvent);
						break;
					}
					case 4 : {
						myEvent = new MyEvent(event, when);
						wednesdayList.add(myEvent);
						break;
					}
					case 5 : {
						myEvent = new MyEvent(event, when);
						thursdaylist.add(myEvent);
						break;
					}
					case 6 : {
						myEvent = new MyEvent(event, when);
						fridaylist.add(myEvent);
						break;
					}
					case 7 : {
						myEvent = new MyEvent(event, when);
						saturdaylist.add(myEvent);
						break;
					}

					}

				}

				Collections.sort(mondaylist);
				Collections.sort(tuesdaylist);
				Collections.sort(wednesdayList);
				Collections.sort(thursdaylist);
				Collections.sort(fridaylist);
				Collections.sort(saturdaylist);
				Collections.sort(sundaylist);

				eventsMap.put(1, mondaylist);
				eventsMap.put(2, tuesdaylist);
				eventsMap.put(3, wednesdayList);
				eventsMap.put(4, thursdaylist);
				eventsMap.put(5, fridaylist);
				eventsMap.put(6, saturdaylist);
				eventsMap.put(7, sundaylist);

				max=0;updateRow();




			}

			return eventsMap;
		}
		else				
			return null;
	}

	public class MyEvent implements Comparable<MyEvent>{

		private CalendarEventEntry calendarEntry;
		private When when;
		public CalendarEventEntry getCalendarEntry() {
			return calendarEntry;
		}
		public void setCalendarEntry(CalendarEventEntry calendarEntry) {
			this.calendarEntry = calendarEntry;
		}
		public String getEventId()
		{
			return calendarEntry.getId();
		}
		public When getWhen() {
			return when;
		}
		public void setWhen(When when) {
			this.when = when;
		}

		public MyEvent(CalendarEventEntry calendarEntry, When when) {
			super();
			this.calendarEntry = calendarEntry;
			this.when = when;
		}
		public MyEvent() {
			super();
			// TODO Auto-generated constructor stub
		}
		@Override
		public int compareTo(MyEvent other) {
			// TODO Auto-generated method stub
			Date myDate = new Date(when.getStartTime().getValue());
			Date otherDate = new Date(other.when.getStartTime().getValue());


			return myDate.compareTo(otherDate);
		}


	}

	@Override
	public void update(Object object) {

		String idDeletedEntry = object.toString().replace("%40", "@");
		for (int i = 1; i < eventsMap.size(); i++) {
			if( eventsMap.get(i).size() > 0)
				for (int j = 0; j < eventsMap.get(i).size(); j++) 
				{
					if (eventsMap.get(i).get(j).getCalendarEntry().getId().replace("%40", "@").equals( idDeletedEntry ))
					{
						eventsMap.get(i).remove(j);
						updateRow();agendTable.updateUI();
						return;
					}
				}
		}

	}

	private void updateRow(){

		max=0;
		for(int index : eventsMap.keySet()){

			if(eventsMap.get(index).size() > max)
				max = eventsMap.get(index).size();
		}

	}
}
